home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / r_alias.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  19KB  |  754 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_alias.c: routines for setting up to draw alias models
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24. #include "d_local.h"    // FIXME: shouldn't be needed (is needed for patch
  25.                         // right now, but that should move)
  26.  
  27. #define LIGHT_MIN    5        // lowest light value we'll allow, to avoid the
  28.                             //  need for inner-loop light clamping
  29.  
  30. mtriangle_t        *ptriangles;
  31. affinetridesc_t    r_affinetridesc;
  32.  
  33. void *            acolormap;    // FIXME: should go away
  34.  
  35. trivertx_t        *r_apverts;
  36.  
  37. // TODO: these probably will go away with optimized rasterization
  38. mdl_t                *pmdl;
  39. static vec3_t                r_plightvec;
  40. static int                    r_ambientlight;
  41. static float                r_shadelight;
  42. aliashdr_t            *paliashdr;
  43. finalvert_t            *pfinalverts;
  44. auxvert_t            *pauxverts;
  45. static float        ziscale;
  46. static model_t        *pmodel;
  47.  
  48. static vec3_t        alias_forward, alias_right, alias_up;
  49.  
  50. static maliasskindesc_t    *pskindesc;
  51.  
  52. int                    r_amodels_drawn;
  53. static int    r_anumverts;
  54.  
  55. float    aliastransform[3][4];
  56.  
  57. typedef struct {
  58.     int    index0;
  59.     int    index1;
  60. } aedge_t;
  61.  
  62. static aedge_t    aedges[12] = {
  63. {0, 1}, {1, 2}, {2, 3}, {3, 0},
  64. {4, 5}, {5, 6}, {6, 7}, {7, 4},
  65. {0, 5}, {1, 4}, {2, 7}, {3, 6}
  66. };
  67.  
  68. #define NUMVERTEXNORMALS    162
  69.  
  70. float    r_avertexnormals[NUMVERTEXNORMALS][3] = {
  71. #include "anorms.h"
  72. };
  73.  
  74. void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,
  75.     stvert_t *pstverts);
  76. void R_AliasSetUpTransform (int trivial_accept);
  77. void R_AliasTransformVector (vec3_t in, vec3_t out);
  78. void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
  79.     trivertx_t *pverts, stvert_t *pstverts);
  80. void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
  81.  
  82.  
  83. /*
  84. ================
  85. R_AliasCheckBBox
  86. ================
  87. */
  88. qboolean R_AliasCheckBBox (void)
  89. {
  90.     int                    i, flags, frame, numv;
  91.     aliashdr_t            *pahdr;
  92.     float                zi, basepts[8][3], v0, v1, frac;
  93.     finalvert_t            *pv0, *pv1, viewpts[16];
  94.     auxvert_t            *pa0, *pa1, viewaux[16];
  95.     maliasframedesc_t    *pframedesc;
  96.     qboolean            zclipped, zfullyclipped;
  97.     unsigned            anyclip, allclip;
  98.     int                    minz;
  99.     
  100. // expand, rotate, and translate points into worldspace
  101.  
  102.     currententity->trivial_accept = 0;
  103.     pmodel = currententity->model;
  104.     pahdr = Mod_Extradata (pmodel);
  105.     pmdl = (mdl_t *)((byte *)pahdr + pahdr->model);
  106.  
  107.     R_AliasSetUpTransform (0);
  108.  
  109. // construct the base bounding box for this frame
  110.     frame = currententity->frame;
  111. // TODO: don't repeat this check when drawing?
  112.     if ((frame >= pmdl->numframes) || (frame < 0))
  113.     {
  114.         Con_DPrintf ("No such frame %d %s\n", frame,
  115.                 pmodel->name);
  116.         frame = 0;
  117.     }
  118.  
  119.     pframedesc = &pahdr->frames[frame];
  120.  
  121. // x worldspace coordinates
  122.     basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
  123.             (float)pframedesc->bboxmin.v[0];
  124.     basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
  125.             (float)pframedesc->bboxmax.v[0];
  126.  
  127. // y worldspace coordinates
  128.     basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
  129.             (float)pframedesc->bboxmin.v[1];
  130.     basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
  131.             (float)pframedesc->bboxmax.v[1];
  132.  
  133. // z worldspace coordinates
  134.     basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
  135.             (float)pframedesc->bboxmin.v[2];
  136.     basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
  137.             (float)pframedesc->bboxmax.v[2];
  138.  
  139.     zclipped = false;
  140.     zfullyclipped = true;
  141.  
  142.     minz = 9999;
  143.     for (i=0; i<8 ; i++)
  144.     {
  145.         R_AliasTransformVector  (&basepts[i][0], &viewaux[i].fv[0]);
  146.  
  147.         if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)
  148.         {
  149.         // we must clip points that are closer than the near clip plane
  150.             viewpts[i].flags = ALIAS_Z_CLIP;
  151.             zclipped = true;
  152.         }
  153.         else
  154.         {
  155.             if (viewaux[i].fv[2] < minz)
  156.                 minz = viewaux[i].fv[2];
  157.             viewpts[i].flags = 0;
  158.             zfullyclipped = false;
  159.         }
  160.     }
  161.  
  162.     
  163.     if (zfullyclipped)
  164.     {
  165.         return false;    // everything was near-z-clipped
  166.     }
  167.  
  168.     numv = 8;
  169.  
  170.     if (zclipped)
  171.     {
  172.     // organize points by edges, use edges to get new points (possible trivial
  173.     // reject)
  174.         for (i=0 ; i<12 ; i++)
  175.         {
  176.         // edge endpoints
  177.             pv0 = &viewpts[aedges[i].index0];
  178.             pv1 = &viewpts[aedges[i].index1];
  179.             pa0 = &viewaux[aedges[i].index0];
  180.             pa1 = &viewaux[aedges[i].index1];
  181.  
  182.         // if one end is clipped and the other isn't, make a new point
  183.             if (pv0->flags ^ pv1->flags)
  184.             {
  185.                 frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
  186.                        (pa1->fv[2] - pa0->fv[2]);
  187.                 viewaux[numv].fv[0] = pa0->fv[0] +
  188.                         (pa1->fv[0] - pa0->fv[0]) * frac;
  189.                 viewaux[numv].fv[1] = pa0->fv[1] +
  190.                         (pa1->fv[1] - pa0->fv[1]) * frac;
  191.                 viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
  192.                 viewpts[numv].flags = 0;
  193.                 numv++;
  194.             }
  195.         }
  196.     }
  197.  
  198. // project the vertices that remain after clipping
  199.     anyclip = 0;
  200.     allclip = ALIAS_XY_CLIP_MASK;
  201.  
  202. // TODO: probably should do this loop in ASM, especially if we use floats
  203.     for (i=0 ; i<numv ; i++)
  204.     {
  205.     // we don't need to bother with vertices that were z-clipped
  206.         if (viewpts[i].flags & ALIAS_Z_CLIP)
  207.             continue;
  208.  
  209.         zi = 1.0 / viewaux[i].fv[2];
  210.  
  211.     // FIXME: do with chop mode in ASM, or convert to float
  212.         v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;
  213.         v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter;
  214.  
  215.         flags = 0;
  216.  
  217.         if (v0 < r_refdef.fvrectx)
  218.             flags |= ALIAS_LEFT_CLIP;
  219.         if (v1 < r_refdef.fvrecty)
  220.             flags |= ALIAS_TOP_CLIP;
  221.         if (v0 > r_refdef.fvrectright)
  222.             flags |= ALIAS_RIGHT_CLIP;
  223.         if (v1 > r_refdef.fvrectbottom)
  224.             flags |= ALIAS_BOTTOM_CLIP;
  225.  
  226.         anyclip |= flags;
  227.         allclip &= flags;
  228.     }
  229.  
  230.     if (allclip)
  231.         return false;    // trivial reject off one side
  232.  
  233.     currententity->trivial_accept = !anyclip & !zclipped;
  234.  
  235.     if (currententity->trivial_accept)
  236.     {
  237.         if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))
  238.         {
  239.             currententity->trivial_accept |= 2;
  240.         }
  241.     }
  242.  
  243.     return true;
  244. }
  245.  
  246.  
  247. /*
  248. ================
  249. R_AliasTransformVector
  250. ================
  251. */
  252. void R_AliasTransformVector (vec3_t in, vec3_t out)
  253. {
  254.     out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];
  255.     out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];
  256.     out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];
  257. }
  258.  
  259.  
  260. /*
  261. ================
  262. R_AliasPreparePoints
  263.  
  264. General clipped case
  265. ================
  266. */
  267. void R_AliasPreparePoints (void)
  268. {
  269.     int            i;
  270.     stvert_t    *pstverts;
  271.     finalvert_t    *fv;
  272.     auxvert_t    *av;
  273.     mtriangle_t    *ptri;
  274.     finalvert_t    *pfv[3];
  275.  
  276.     pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
  277.     r_anumverts = pmdl->numverts;
  278.      fv = pfinalverts;
  279.     av = pauxverts;
  280.  
  281.     for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++)
  282.     {
  283.         R_AliasTransformFinalVert (fv, av, r_apverts, pstverts);
  284.         if (av->fv[2] < ALIAS_Z_CLIP_PLANE)
  285.             fv->flags |= ALIAS_Z_CLIP;
  286.         else
  287.         {
  288.              R_AliasProjectFinalVert (fv, av);
  289.  
  290.             if (fv->v[0] < r_refdef.aliasvrect.x)
  291.                 fv->flags |= ALIAS_LEFT_CLIP;
  292.             if (fv->v[1] < r_refdef.aliasvrect.y)
  293.                 fv->flags |= ALIAS_TOP_CLIP;
  294.             if (fv->v[0] > r_refdef.aliasvrectright)
  295.                 fv->flags |= ALIAS_RIGHT_CLIP;
  296.             if (fv->v[1] > r_refdef.aliasvrectbottom)
  297.                 fv->flags |= ALIAS_BOTTOM_CLIP;    
  298.         }
  299.     }
  300.  
  301. //
  302. // clip and draw all triangles
  303. //
  304.     r_affinetridesc.numtriangles = 1;
  305.  
  306.     ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
  307.     for (i=0 ; i<pmdl->numtris ; i++, ptri++)
  308.     {
  309.         pfv[0] = &pfinalverts[ptri->vertindex[0]];
  310.         pfv[1] = &pfinalverts[ptri->vertindex[1]];
  311.         pfv[2] = &pfinalverts[ptri->vertindex[2]];
  312.  
  313.         if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )
  314.             continue;        // completely clipped
  315.         
  316.         if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
  317.             (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )
  318.         {    // totally unclipped
  319.             r_affinetridesc.pfinalverts = pfinalverts;
  320.             r_affinetridesc.ptriangles = ptri;
  321.             D_PolysetDraw ();
  322.         }
  323.         else        
  324.         {    // partially clipped
  325.             R_AliasClipTriangle (ptri);
  326.         }
  327.     }
  328. }
  329.  
  330.  
  331. /*
  332. ================
  333. R_AliasSetUpTransform
  334. ================
  335. */
  336. void R_AliasSetUpTransform (int trivial_accept)
  337. {
  338.     int                i;
  339.     float            rotationmatrix[3][4], t2matrix[3][4];
  340.     static float    tmatrix[3][4];
  341.     static float    viewmatrix[3][4];
  342.     vec3_t            angles;
  343.  
  344. // TODO: should really be stored with the entity instead of being reconstructed
  345. // TODO: should use a look-up table
  346. // TODO: could cache lazily, stored in the entity
  347.  
  348.     angles[ROLL] = currententity->angles[ROLL];
  349.     angles[PITCH] = -currententity->angles[PITCH];
  350.     angles[YAW] = currententity->angles[YAW];
  351.     AngleVectors (angles, alias_forward, alias_right, alias_up);
  352.  
  353.     tmatrix[0][0] = pmdl->scale[0];
  354.     tmatrix[1][1] = pmdl->scale[1];
  355.     tmatrix[2][2] = pmdl->scale[2];
  356.  
  357.     tmatrix[0][3] = pmdl->scale_origin[0];
  358.     tmatrix[1][3] = pmdl->scale_origin[1];
  359.     tmatrix[2][3] = pmdl->scale_origin[2];
  360.  
  361. // TODO: can do this with simple matrix rearrangement
  362.  
  363.     for (i=0 ; i<3 ; i++)
  364.     {
  365.         t2matrix[i][0] = alias_forward[i];
  366.         t2matrix[i][1] = -alias_right[i];
  367.         t2matrix[i][2] = alias_up[i];
  368.     }
  369.  
  370.     t2matrix[0][3] = -modelorg[0];
  371.     t2matrix[1][3] = -modelorg[1];
  372.     t2matrix[2][3] = -modelorg[2];
  373.  
  374. // FIXME: can do more efficiently than full concatenation
  375.     R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
  376.  
  377. // TODO: should be global, set when vright, etc., set
  378.     VectorCopy (vright, viewmatrix[0]);
  379.     VectorCopy (vup, viewmatrix[1]);
  380.     VectorInverse (viewmatrix[1]);
  381.     VectorCopy (vpn, viewmatrix[2]);
  382.  
  383. //    viewmatrix[0][3] = 0;
  384. //    viewmatrix[1][3] = 0;
  385. //    viewmatrix[2][3] = 0;
  386.  
  387.     R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform);
  388.  
  389. // do the scaling up of x and y to screen coordinates as part of the transform
  390. // for the unclipped case (it would mess up clipping in the clipped case).
  391. // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
  392. // correspondingly so the projected x and y come out right
  393. // FIXME: make this work for clipped case too?
  394.     if (trivial_accept)
  395.     {
  396.         for (i=0 ; i<4 ; i++)
  397.         {
  398.             aliastransform[0][i] *= aliasxscale *
  399.                     (1.0 / ((float)0x8000 * 0x10000));
  400.             aliastransform[1][i] *= aliasyscale *
  401.                     (1.0 / ((float)0x8000 * 0x10000));
  402.             aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000);
  403.  
  404.         }
  405.     }
  406. }
  407.  
  408.  
  409. /*
  410. ================
  411. R_AliasTransformFinalVert
  412. ================
  413. */
  414. void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
  415.     trivertx_t *pverts, stvert_t *pstverts)
  416. {
  417.     int        temp;
  418.     float    lightcos, *plightnormal;
  419.  
  420.     av->fv[0] = DotProduct(pverts->v, aliastransform[0]) +
  421.             aliastransform[0][3];
  422.     av->fv[1] = DotProduct(pverts->v, aliastransform[1]) +
  423.             aliastransform[1][3];
  424.     av->fv[2] = DotProduct(pverts->v, aliastransform[2]) +
  425.             aliastransform[2][3];
  426.  
  427.     fv->v[2] = pstverts->s;
  428.     fv->v[3] = pstverts->t;
  429.  
  430.     fv->flags = pstverts->onseam;
  431.  
  432. // lighting
  433.     plightnormal = r_avertexnormals[pverts->lightnormalindex];
  434.     lightcos = DotProduct (plightnormal, r_plightvec);
  435.     temp = r_ambientlight;
  436.  
  437.     if (lightcos < 0)
  438.     {
  439.         temp += (int)(r_shadelight * lightcos);
  440.  
  441.     // clamp; because we limited the minimum ambient and shading light, we
  442.     // don't have to clamp low light, just bright
  443.         if (temp < 0)
  444.             temp = 0;
  445.     }
  446.  
  447.     fv->v[4] = temp;
  448. }
  449.  
  450.  
  451. #if    !id386
  452.  
  453. /*
  454. ================
  455. R_AliasTransformAndProjectFinalVerts
  456. ================
  457. */
  458. void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
  459. {
  460.     int            i, temp;
  461.     float        lightcos, *plightnormal, zi;
  462.     trivertx_t    *pverts;
  463.  
  464.     pverts = r_apverts;
  465.  
  466.     for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
  467.     {
  468.     // transform and project
  469.         zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
  470.                 aliastransform[2][3]);
  471.  
  472.     // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
  473.     // scaled up by 1/2**31, and the scaling cancels out for x and y in the
  474.     // projection
  475.         fv->v[5] = zi;
  476.  
  477.         fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
  478.                 aliastransform[0][3]) * zi) + aliasxcenter;
  479.         fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
  480.                 aliastransform[1][3]) * zi) + aliasycenter;
  481.  
  482.         fv->v[2] = pstverts->s;
  483.         fv->v[3] = pstverts->t;
  484.         fv->flags = pstverts->onseam;
  485.  
  486.     // lighting
  487.         plightnormal = r_avertexnormals[pverts->lightnormalindex];
  488.         lightcos = DotProduct (plightnormal, r_plightvec);
  489.         temp = r_ambientlight;
  490.  
  491.         if (lightcos < 0)
  492.         {
  493.             temp += (int)(r_shadelight * lightcos);
  494.  
  495.         // clamp; because we limited the minimum ambient and shading light, we
  496.         // don't have to clamp low light, just bright
  497.             if (temp < 0)
  498.                 temp = 0;
  499.         }
  500.  
  501.         fv->v[4] = temp;
  502.     }
  503. }
  504.  
  505. #endif
  506.  
  507.  
  508. /*
  509. ================
  510. R_AliasProjectFinalVert
  511. ================
  512. */
  513. void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
  514. {
  515.     float    zi;
  516.  
  517. // project points
  518.     zi = 1.0 / av->fv[2];
  519.  
  520.     fv->v[5] = zi * ziscale;
  521.  
  522.     fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
  523.     fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
  524. }
  525.  
  526.  
  527. /*
  528. ================
  529. R_AliasPrepareUnclippedPoints
  530. ================
  531. */
  532. void R_AliasPrepareUnclippedPoints (void)
  533. {
  534.     stvert_t    *pstverts;
  535.     finalvert_t    *fv;
  536.  
  537.     pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
  538.     r_anumverts = pmdl->numverts;
  539. // FIXME: just use pfinalverts directly?
  540.     fv = pfinalverts;
  541.  
  542.     R_AliasTransformAndProjectFinalVerts (fv, pstverts);
  543.  
  544.     if (r_affinetridesc.drawtype)
  545.         D_PolysetDrawFinalVerts (fv, r_anumverts);
  546.  
  547.     r_affinetridesc.pfinalverts = pfinalverts;
  548.     r_affinetridesc.ptriangles = (mtriangle_t *)
  549.             ((byte *)paliashdr + paliashdr->triangles);
  550.     r_affinetridesc.numtriangles = pmdl->numtris;
  551.  
  552.     D_PolysetDraw ();
  553. }
  554.  
  555. /*
  556. ===============
  557. R_AliasSetupSkin
  558. ===============
  559. */
  560. void R_AliasSetupSkin (void)
  561. {
  562.     int                    a_skinwidth;
  563.     int                    skinnum;
  564.     int                    i, numskins;
  565.     maliasskingroup_t    *paliasskingroup;
  566.     float                *pskinintervals, fullskininterval;
  567.     float                skintargettime, skintime;
  568.  
  569.     skinnum = currententity->skinnum;
  570.     if ((skinnum >= pmdl->numskins) || (skinnum < 0))
  571.     {
  572.         Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
  573.         skinnum = 0;
  574.     }
  575.  
  576.     pskindesc = ((maliasskindesc_t *)
  577.             ((byte *)paliashdr + paliashdr->skindesc)) + skinnum;
  578.     a_skinwidth = pmdl->skinwidth;
  579.  
  580.     if (pskindesc->type == ALIAS_SKIN_GROUP)
  581.     {
  582.         paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr +
  583.                 pskindesc->skin);
  584.         pskinintervals = (float *)
  585.                 ((byte *)paliashdr + paliasskingroup->intervals);
  586.         numskins = paliasskingroup->numskins;
  587.         fullskininterval = pskinintervals[numskins-1];
  588.     
  589.         skintime = cl.time + currententity->syncbase;
  590.     
  591.     // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval
  592.     // values are positive, so we don't have to worry about division by 0
  593.         skintargettime = skintime -
  594.                 ((int)(skintime / fullskininterval)) * fullskininterval;
  595.     
  596.         for (i=0 ; i<(numskins-1) ; i++)
  597.         {
  598.             if (pskinintervals[i] > skintargettime)
  599.                 break;
  600.         }
  601.     
  602.         pskindesc = &paliasskingroup->skindescs[i];
  603.     }
  604.  
  605.     r_affinetridesc.pskindesc = pskindesc;
  606.     r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin);
  607.     r_affinetridesc.skinwidth = a_skinwidth;
  608.     r_affinetridesc.seamfixupX16 =  (a_skinwidth >> 1) << 16;
  609.     r_affinetridesc.skinheight = pmdl->skinheight;
  610. }
  611.  
  612. /*
  613. ================
  614. R_AliasSetupLighting
  615. ================
  616. */
  617. void R_AliasSetupLighting (alight_t *plighting)
  618. {
  619.  
  620. // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
  621. // to clamp off the bottom
  622.     r_ambientlight = plighting->ambientlight;
  623.  
  624.     if (r_ambientlight < LIGHT_MIN)
  625.         r_ambientlight = LIGHT_MIN;
  626.  
  627.     r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
  628.  
  629.     if (r_ambientlight < LIGHT_MIN)
  630.         r_ambientlight = LIGHT_MIN;
  631.  
  632.     r_shadelight = plighting->shadelight;
  633.  
  634.     if (r_shadelight < 0)
  635.         r_shadelight = 0;
  636.  
  637.     r_shadelight *= VID_GRADES;
  638.  
  639. // rotate the lighting vector into the model's frame of reference
  640.     r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
  641.     r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
  642.     r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
  643. }
  644.  
  645. /*
  646. =================
  647. R_AliasSetupFrame
  648.  
  649. set r_apverts
  650. =================
  651. */
  652. void R_AliasSetupFrame (void)
  653. {
  654.     int                frame;
  655.     int                i, numframes;
  656.     maliasgroup_t    *paliasgroup;
  657.     float            *pintervals, fullinterval, targettime, time;
  658.  
  659.     frame = currententity->frame;
  660.     if ((frame >= pmdl->numframes) || (frame < 0))
  661.     {
  662.         Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
  663.         frame = 0;
  664.     }
  665.  
  666.     if (paliashdr->frames[frame].type == ALIAS_SINGLE)
  667.     {
  668.         r_apverts = (trivertx_t *)
  669.                 ((byte *)paliashdr + paliashdr->frames[frame].frame);
  670.         return;
  671.     }
  672.     
  673.     paliasgroup = (maliasgroup_t *)
  674.                 ((byte *)paliashdr + paliashdr->frames[frame].frame);
  675.     pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals);
  676.     numframes = paliasgroup->numframes;
  677.     fullinterval = pintervals[numframes-1];
  678.  
  679.     time = cl.time + currententity->syncbase;
  680.  
  681. //
  682. // when loading in Mod_LoadAliasGroup, we guaranteed all interval values
  683. // are positive, so we don't have to worry about division by 0
  684. //
  685.     targettime = time - ((int)(time / fullinterval)) * fullinterval;
  686.  
  687.     for (i=0 ; i<(numframes-1) ; i++)
  688.     {
  689.         if (pintervals[i] > targettime)
  690.             break;
  691.     }
  692.  
  693.     r_apverts = (trivertx_t *)
  694.                 ((byte *)paliashdr + paliasgroup->frames[i].frame);
  695. }
  696.  
  697.  
  698. /*
  699. ================
  700. R_AliasDrawModel
  701. ================
  702. */
  703. void R_AliasDrawModel (alight_t *plighting)
  704. {
  705.     finalvert_t        finalverts[MAXALIASVERTS +
  706.                         ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1];
  707.     auxvert_t        auxverts[MAXALIASVERTS];
  708.  
  709.     r_amodels_drawn++;
  710.  
  711. // cache align
  712.     pfinalverts = (finalvert_t *)
  713.             (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
  714.     pauxverts = &auxverts[0];
  715.  
  716.     paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
  717.     pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
  718.  
  719.     R_AliasSetupSkin ();
  720.     R_AliasSetUpTransform (currententity->trivial_accept);
  721.     R_AliasSetupLighting (plighting);
  722.     R_AliasSetupFrame ();
  723.  
  724.     if (!currententity->colormap)
  725.         Sys_Error ("R_AliasDrawModel: !currententity->colormap");
  726.  
  727.     r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
  728.             r_recursiveaffinetriangles;
  729.  
  730.     if (r_affinetridesc.drawtype)
  731.     {
  732.         D_PolysetUpdateTables ();        // FIXME: precalc...
  733.     }
  734.     else
  735.     {
  736. #if    id386
  737.         D_Aff8Patch (currententity->colormap);
  738. #endif
  739.     }
  740.  
  741.     acolormap = currententity->colormap;
  742.  
  743.     if (currententity != &cl.viewent)
  744.         ziscale = (float)0x8000 * (float)0x10000;
  745.     else
  746.         ziscale = (float)0x8000 * (float)0x10000 * 3.0;
  747.  
  748.     if (currententity->trivial_accept)
  749.         R_AliasPrepareUnclippedPoints ();
  750.     else
  751.         R_AliasPreparePoints ();
  752. }
  753.  
  754.